Skip to content

Conversation

@cyfung1031
Copy link
Collaborator

@cyfung1031 cyfung1031 commented Nov 7, 2025

概述 Descriptions

之前 @early-start 的代码修改,导致 #704 的修改被倒回去了
现在重做 #704

历史原因,scripting.RegisteredContentScript 的设计不是用来做 自订脚本 用途,不支持动态代码。
它只支持url 网址,,而不支持 code 代码
这个PR做了在网址取 flags 的处理,因此不需要 code

但相反 chrome 不支持网址参数,因此还是用 userScripts API 做注入

已测试过能在 Firefox & Chrome 顺利执行

变更内容 Changes

截图 Screenshots

@cyfung1031 cyfung1031 marked this pull request as draft November 7, 2025 18:25
@cyfung1031 cyfung1031 force-pushed the pr-704b branch 2 times, most recently from 96352e8 to deea0bc Compare November 7, 2025 18:52
@cyfung1031 cyfung1031 marked this pull request as ready for review November 7, 2025 18:52
@cyfung1031 cyfung1031 force-pushed the pr-704b branch 2 times, most recently from 4f9723b to 01bb9fa Compare November 17, 2025 09:50
@cyfung1031 cyfung1031 changed the base branch from main to release/v1.3 November 17, 2025 09:51
@cyfung1031 cyfung1031 changed the title userScripts / scripting API 调整,增强兼容性 ( 重做 #704 ) [暂定v1.3] userScripts / scripting API 调整,增强兼容性 ( 重做 #704 ) Nov 17, 2025
@cyfung1031 cyfung1031 changed the title [暂定v1.3] userScripts / scripting API 调整,增强兼容性 ( 重做 #704 ) [v1.3] userScripts / scripting API 调整,增强兼容性 ( 重做 #704 ) Nov 22, 2025
@CodFrm CodFrm requested a review from Copilot November 28, 2025 03:59
Copilot finished reviewing on behalf of CodFrm November 28, 2025 04:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

此 PR 重做了 #704 的修改,解决了 userScripts 和 scripting API 的兼容性问题。主要目标是适配 Firefox 和 Chrome 在脚本注入机制上的差异:Firefox 不支持动态代码注入,需要通过 URL 参数传递 MessageFlag;而 Chrome 不支持 URL 查询参数,继续使用 userScripts API 的代码注入方式。

  • 引入 getUspMessageFlag() 函数从错误堆栈中提取 URL 参数
  • 重构脚本注册逻辑,区分 Firefox(scripting API)和 Chrome(userScripts API)两种注册方式
  • 更新 ID 检查从 "scriptcat-content" 改为 "scriptcat-inject"

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 12 comments.

File Description
src/pkg/utils/utils.ts 新增 getUspMessageFlag() 函数用于从堆栈提取 URL 参数;更新 checkUserScriptsAvailable() 的 ID 检查
src/content.ts 更新 MessageFlag 获取逻辑,支持从 arguments 或 URL 参数中获取;改进错误处理和注释说明
src/app/service/service_worker/runtime.ts 重构 getContentAndInjectScript() 返回分离的 content 和 inject 脚本列表;Firefox 使用 scripting API 注册 content.js(URL参数),Chrome 使用 userScripts API(代码注入);更新注册和检查逻辑;移除 compileInjectUserScript() 方法

// getContentAndInjectScript依赖loadScriptMatchInfo
// 需要等getParticularScriptList完成后再执行
const generalScriptList = await this.getContentAndInjectScript(options);
const { inject: injectScripList, content: contentScriptList } = await this.getContentAndInjectScript(options);
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

变量名拼写错误(与第920行相同):injectScripList 应该是 injectScriptList(缺少字母 't')。

Copilot uses AI. Check for mistakes.
Comment on lines 833 to 834
}
const retScript: chrome.userScripts.RegisteredUserScript[] = [];
const contentJs = await this.getContentJsCode();
if (contentJs) {
const codeBody = `(function (MessageFlag) {\n${contentJs}\n})('${messageFlag}')`;
const code = `${codeBody}${sourceMapTo("scriptcat-content.js")}\n`;
retScript.push({
id: "scriptcat-content",
js: [{ code }],
matches: ["<all_urls>"],
allFrames: true,
runAt: "document_start",
world: "USER_SCRIPT",
excludeMatches,
excludeGlobs,
});
}

Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

返回类型的命名不够清晰:函数返回对象的键名 contentinject 没有明确表明它们分别对应不同的 API。

考虑到:

  • content 仅在 Firefox 中使用,通过 scripting.RegisteredContentScript
  • inject 在两个浏览器中使用,通过 userScripts.RegisteredUserScript

建议改进返回对象的结构或添加 JSDoc 注释,明确说明:

  • content: 用于 Firefox 的 scripting API 注册的脚本列表
  • inject: 用于 userScripts API 注册的脚本列表(包括 inject.js 和 Chrome 下的 content.js)

这样可以提高代码的可读性和可维护性。

Copilot uses AI. Check for mistakes.
// 判断是否已经注册过
if (runtimeGlobal.registered) {
// 异常情况
// 检查scriptcat-content和scriptcat-inject是否存在
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释与代码不一致:注释提到"检查scriptcat-content和scriptcat-inject是否存在",但代码第895行只检查了 "scriptcat-inject"。

由于新架构中:

  • Firefox: scriptcat-content 通过 scripting API 注册(不在 userScripts 中)
  • Chrome: scriptcat-content 通过 userScripts API 注册(在 userScripts 中)

建议更新注释以准确反映实际检查的内容,例如:"检查scriptcat-inject是否存在"

Suggested change
// 检查scriptcat-content和scriptcat-inject是否存在
// 检查scriptcat-inject是否存在
// 说明:scriptcat-content 在 Firefox 通过 scripting API 注册(不在 userScripts 中),
// 在 Chrome 通过 userScripts API 注册(在 userScripts 中),此处仅检查 scriptcat-inject 是否存在

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +65
export const getUspMessageFlag = () => {
const s = new Error().stack;
if (s) {
const search1 = "content.js?usp_flag=";
const len1 = search1.length;
const idx1 = s.indexOf(search1);
if (idx1 > 0) {
const search2 = "&usp_end";
const idx2 = s.indexOf(search2, idx1 + len1);
if (idx2 > 0) {
const param = s.substring(idx1 + len1, idx2);
try {
// 使用 URLSearchParams 避免字符编码问题
const uspString = `usp_flag=${param}`;
const usp = new URLSearchParams(uspString);
if (usp.size === 1) return usp.get("usp_flag") || null;
} catch (e) {
console.error(e);
}
}
}
}
return null;
};
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新增的 getUspMessageFlag() 函数缺少测试覆盖。该函数通过解析错误堆栈提取 URL 参数,属于核心功能逻辑,应该有测试确保:

  1. 能够正确从堆栈中提取 usp_flag 参数
  2. 正确处理 URLSearchParams 解码
  3. 对于无效或缺失的参数返回 null
  4. 正确处理错误情况

建议在 src/pkg/utils/utils.test.ts 中添加相应的测试用例。

Copilot uses AI. Check for mistakes.
retContent = [
{
id: "scriptcat-content",
js: [`/src/content.js?${new URLSearchParams({ usp_flag: messageFlag })}&usp_end`],
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL 构建方式不够清晰:使用字符串拼接 ?${...}&usp_end 的方式可能让人混淆 &usp_end 的意图。

虽然 &usp_end 是一个用于标记参数结束位置的标识符(用于从堆栈字符串中提取),但这种直接拼接的方式不够直观。建议:

  1. 添加注释说明 &usp_end 的作用
  2. 或者使用更清晰的方式构建,例如:
js: [`/src/content.js?${new URLSearchParams({ usp_flag: messageFlag, usp_end: '' })}`]

这样可以让代码意图更明确,便于后续维护。

Suggested change
js: [`/src/content.js?${new URLSearchParams({ usp_flag: messageFlag })}&usp_end`],
// 使用 URLSearchParams 构建 usp_flagusp_end 参数,避免字符串拼接歧义
js: [`/src/content.js?${new URLSearchParams({ usp_flag: messageFlag, usp_end: "" })}`],

Copilot uses AI. Check for mistakes.
if (res.length === 1) {
return;
}
// scriptcat-content/scriptcat-inject不存在的情况
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释不准确:注释提到 "scriptcat-content/scriptcat-inject不存在的情况",但代码实际上只检查了 scriptcat-inject 的存在性(第895行)。

建议更新注释为:"scriptcat-inject不存在的情况",以准确反映实际逻辑。

Suggested change
// scriptcat-content/scriptcat-inject不存在的情况
// scriptcat-inject不存在的情况

Copilot uses AI. Check for mistakes.
const search1 = "content.js?usp_flag=";
const len1 = search1.length;
const idx1 = s.indexOf(search1);
if (idx1 > 0) {
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

条件检查 idx1 > 0 应该使用 idx1 >= 0

String.indexOf() 在找到匹配时返回索引位置(可能为0),找不到时返回-1。当搜索字符串在位置0时,当前条件会错过该匹配。虽然在实际场景中 "content.js?usp_flag=" 不太可能出现在堆栈字符串的开头(位置0),但使用 >= 0 更符合 indexOf 的标准用法,提高代码的正确性和可读性。

Suggested change
if (idx1 > 0) {
if (idx1 >= 0) {

Copilot uses AI. Check for mistakes.
if (idx1 > 0) {
const search2 = "&usp_end";
const idx2 = s.indexOf(search2, idx1 + len1);
if (idx2 > 0) {
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

条件检查 idx2 > 0 应该使用 idx2 > idx1 + len1

当前条件只检查 idx2 > 0,这意味着如果 "&usp_end" 出现在 "content.js?usp_flag=" 之前(虽然不太可能),代码仍会尝试提取参数,导致 substring(idx1 + len1, idx2) 返回空字符串或负索引。更正确的检查应该是 idx2 > idx1 + len1,确保 "&usp_end" 在 "content.js?usp_flag=" 之后。

Suggested change
if (idx2 > 0) {
if (idx2 > idx1 + len1) {

Copilot uses AI. Check for mistakes.

/* global MessageFlag */
// @ts-ignore
const MessageFlag: string | null = (typeof arguments === "object" && arguments?.[0]) || getUspMessageFlag();
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

类型检查不够严谨:条件 typeof arguments === "object" 应该使用 typeof arguments === "object" && arguments !== null

虽然 arguments 在实际运行中不太可能为 null,但 typeof null === "object" 在 JavaScript 中为 true,这是一个已知的语言特性。建议添加 null 检查以确保代码的健壮性和准确性。

Suggested change
const MessageFlag: string | null = (typeof arguments === "object" && arguments?.[0]) || getUspMessageFlag();
const MessageFlag: string | null = (typeof arguments === "object" && arguments !== null && arguments?.[0]) || getUspMessageFlag();

Copilot uses AI. Check for mistakes.
@CodFrm CodFrm merged commit 43bc40f into scriptscat:release/v1.3 Nov 28, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants